/**
 * JWT Token 解析工具
 */

/**
 * Token 载荷接口（只包含用户基本信息，不包含权限）
 */
export interface TokenPayload {
  /** 主题（用户名） */
  sub: string;
  /** 受众 */
  aud: string;
  /** 不早于时间 */
  nbf: number;
  /** 签发者 */
  iss: string;
  /** 过期时间 */
  exp: number;
  /** 签发时间 */
  iat: number;
  /** 用户ID */
  userId: number;
  /** JWT ID */
  jti: string;
  /** 用户名 */
  username: string;
}

/**
 * 解析 JWT Token（不验证签名）
 * @param token JWT Token 字符串
 * @returns Token 载荷对象，解析失败返回 null
 */
export function parseJwtToken(token: string): TokenPayload | null {
  if (!token) {
    return null;
  }

  try {
    // JWT 格式：header.payload.signature
    const parts = token.split('.');
    if (parts.length !== 3) {
      console.error('Invalid JWT format');
      return null;
    }

    // 解码 payload（Base64URL 解码）
    const payload = parts[1];
    const decodedPayload = base64UrlDecode(payload);

    // 解析 JSON
    const parsedPayload = JSON.parse(decodedPayload) as TokenPayload;

    return parsedPayload;
  } catch (error) {
    console.error('Failed to parse JWT token:', error);
    return null;
  }
}

/**
 * Base64URL 解码
 * @param str Base64URL 编码的字符串
 * @returns 解码后的字符串
 */
function base64UrlDecode(str: string): string {
  // Base64URL 转 Base64
  let base64 = str.replace(/-/g, '+').replace(/_/g, '/');

  // 补齐 padding
  const pad = base64.length % 4;
  if (pad) {
    if (pad === 1) {
      throw new Error('Invalid Base64URL string');
    }
    base64 += '='.repeat(4 - pad);
  }

  // Base64 解码
  try {
    // 使用 atob 解码（浏览器环境）
    const decoded = atob(base64);
    // 处理 UTF-8 编码
    return decodeURIComponent(
      decoded
        .split('')
        .map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
        .join(''),
    );
  } catch (error) {
    throw new Error('Failed to decode Base64URL string');
  }
}

/**
 * 检查 Token 是否过期
 * @param token JWT Token 字符串或载荷对象
 * @returns true 表示已过期，false 表示未过期
 */
export function isTokenExpired(token: string | TokenPayload): boolean {
  const payload = typeof token === 'string' ? parseJwtToken(token) : token;

  if (!payload || !payload.exp) {
    return true;
  }

  // exp 是秒级时间戳，需要转换为毫秒
  const expirationTime = payload.exp * 1000;
  const currentTime = Date.now();

  return currentTime >= expirationTime;
}

/**
 * 获取 Token 剩余有效时间（秒）
 * @param token JWT Token 字符串或载荷对象
 * @returns 剩余秒数，已过期返回 0
 */
export function getTokenRemainingTime(token: string | TokenPayload): number {
  const payload = typeof token === 'string' ? parseJwtToken(token) : token;

  if (!payload || !payload.exp) {
    return 0;
  }

  const expirationTime = payload.exp * 1000;
  const currentTime = Date.now();
  const remaining = Math.floor((expirationTime - currentTime) / 1000);

  return remaining > 0 ? remaining : 0;
}

/**
 * 格式化 Token 过期时间
 * @param token JWT Token 字符串或载荷对象
 * @returns 格式化的日期时间字符串
 */
export function formatTokenExpiration(token: string | TokenPayload): string {
  const payload = typeof token === 'string' ? parseJwtToken(token) : token;

  if (!payload || !payload.exp) {
    return '未知';
  }

  const expirationTime = payload.exp * 1000;
  const date = new Date(expirationTime);

  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  });
}

/**
 * 从 Token 中提取用户信息（只包含基本信息，不包含权限）
 * @param token JWT Token 字符串
 * @returns 用户信息对象
 */
export function extractUserInfoFromToken(token: string) {
  const payload = parseJwtToken(token);

  if (!payload) {
    return null;
  }

  return {
    userId: payload.userId,
    username: payload.username,
  };
}

/**
 * 从 Token 中提取权限信息（Token 中不再包含权限，返回空数组）
 * @param token JWT Token 字符串
 * @returns 权限信息对象（空）
 * @deprecated Token 中不再包含权限信息，请使用 getCurrentUserPermissions 接口获取权限
 */
export function extractPermissionsFromToken(token: string) {
  // Token 中不再包含权限信息，返回空数组
  return {
    buttonPermCodes: [],
    menuPermCodes: [],
    urlPermCodes: [],
    allPermCodes: [],
  };
}

/**
 * 检查是否拥有指定权限（已废弃，Token 中不再包含权限信息）
 * @deprecated Token 中不再包含权限信息，请使用 accessStore.accessCodes 检查权限
 */
export function hasPermissionInToken(
  token: string,
  permissionCode: string,
  type: 'button' | 'menu' | 'url' | 'any' = 'any',
): boolean {
  console.warn('[hasPermissionInToken] 已废弃：Token 中不再包含权限信息，请使用 accessStore.accessCodes 检查权限');
  return false;
}

/**
 * 检查是否拥有指定角色（已废弃，Token 中不再包含角色信息）
 * @deprecated Token 中不再包含角色信息，请使用 userStore.userInfo.roles 检查角色
 */
export function hasRoleInToken(token: string, role: string): boolean {
  console.warn('[hasRoleInToken] 已废弃：Token 中不再包含角色信息，请使用 userStore.userInfo.roles 检查角色');
  return false;
}

/**
 * 检查是否拥有任一指定角色（已废弃）
 * @deprecated Token 中不再包含角色信息，请使用 userStore.userInfo.roles 检查角色
 */
export function hasAnyRoleInToken(token: string, roles: string[]): boolean {
  console.warn('[hasAnyRoleInToken] 已废弃：Token 中不再包含角色信息，请使用 userStore.userInfo.roles 检查角色');
  return false;
}

/**
 * 检查是否拥有所有指定角色（已废弃）
 * @deprecated Token 中不再包含角色信息，请使用 userStore.userInfo.roles 检查角色
 */
export function hasAllRolesInToken(token: string, roles: string[]): boolean {
  console.warn('[hasAllRolesInToken] 已废弃：Token 中不再包含角色信息，请使用 userStore.userInfo.roles 检查角色');
  return false;
}

/**
 * 打印 Token 信息（调试用）
 * @param token JWT Token 字符串
 */
export function debugToken(token: string): void {
  const payload = parseJwtToken(token);

  if (!payload) {
    console.error('❌ Invalid token');
    return;
  }

  console.group('🔐 JWT Token Information');
  console.log('👤 用户信息:');
  console.log('  - 用户ID:', payload.userId);
  console.log('  - 用户名:', payload.username);

  console.log('\n⏰ 时间信息:');
  console.log('  - 签发时间:', new Date(payload.iat * 1000).toLocaleString('zh-CN'));
  console.log('  - 过期时间:', new Date(payload.exp * 1000).toLocaleString('zh-CN'));
  console.log('  - 剩余时间:', getTokenRemainingTime(payload), '秒');
  console.log('  - 是否过期:', isTokenExpired(payload) ? '是' : '否');

  console.log('\n📋 其他信息:');
  console.log('  - 签发者:', payload.iss);
  console.log('  - 受众:', payload.aud);
  console.log('  - JWT ID:', payload.jti);

  console.log('\n💡 提示:');
  console.log('  - Token 中不包含权限信息');
  console.log('  - 权限信息通过 getCurrentUserPermissions 接口获取');

  console.groupEnd();
}

